/**
 * @file user_gpio.c
 * @author Victor Lau (1345236485@qq.com)
 * @brief 
 * @version 0.1
 * @date 2023-07-19
 * 
 * @copyright Copyright (c) 2023 Victor Lau. All rights reserved.
 * 
 */
#include "user_gpio.h"
#include "include.h"
#include "/usr/include/linux/input.h"
#include "user_eth1.h"

#define RLED_DEV_PATH                   "/sys/class/leds/red/brightness"
#define GLED_DEV_PATH                   "/sys/class/leds/green/brightness"
#define BLED_DEV_PATH                   "/sys/class/leds/blue/brightness"
#define LED_2G_DEV_PATH              "/sys/class/leds/led4/brightness"
#define LED_5G_DEV_PATH              "/sys/class/leds/led5/brightness"

struct input_event button_input_event;
int fd_rx, fd_tx, fd_eth, fd_2g, fd_5g;

int _client_ioctl_init(void)
{
        int fd;
        //index config
        fd = open("/sys/class/gpio/export", O_WRONLY);
        if(fd < 0)
                return 1 ;

        write(fd, RS485_GPIO_CTRL, strlen(RS485_GPIO_CTRL));
        close(fd);

        //direction config
        fd = open("/sys/class/gpio/gpio" RS485_GPIO_CTRL "/direction", O_WRONLY);
        if(fd < 0)
                return 2;

        write(fd, "out", strlen("out"));
        close(fd);

        return 0;
}

int _client_ioctl_on(void)
{
        int fd;

        fd = open("/sys/class/gpio/gpio" RS485_GPIO_CTRL "/value", O_WRONLY);
        if(fd < 0)
                return 1;

        write(fd, "0", 1);
        close(fd);

        return 0;
}

int _client_ioctl_off(void)
{
        int fd;

        fd = open("/sys/class/gpio/gpio" RS485_GPIO_CTRL "/value", O_WRONLY);
        if(fd < 0)
                return 1;

        write(fd, "1", 1);
        close(fd);

        return 0;
}

#if 0
int user_2g_led_init(void)
{
        int fd;
        //index config
        fd = open("/sys/class/gpio/export", O_WRONLY);
        if(fd < 0)
                return 1 ;

        write(fd, LED4_GPIO_CTRL, strlen(LED4_GPIO_CTRL));
        close(fd);

        //direction config
        fd = open("/sys/class/gpio/gpio" LED4_GPIO_CTRL "/direction", O_WRONLY);
        if(fd < 0)
                return 2;

        write(fd, "out", strlen("out"));
        close(fd);

        return 0;
}

int user_5g_led_init(void)
{
        int fd;
        //index config
        fd = open("/sys/class/gpio/export", O_WRONLY);
        if(fd < 0)
                return 1 ;

        write(fd, LED5_GPIO_CTRL, strlen(LED5_GPIO_CTRL));
        close(fd);

        //direction config
        fd = open("/sys/class/gpio/gpio" LED5_GPIO_CTRL "/direction", O_WRONLY);
        if(fd < 0)
                return 2;

        write(fd, "out", strlen("out"));
        close(fd);

        return 0;
}


int led_2g_on(void)
{
        int fd;

        fd = open("/sys/class/gpio/gpio" LED4_GPIO_CTRL "/value", O_WRONLY);
        if(fd < 0)
                return 1;

        write(fd, "0", 1);
        close(fd);

        return 0;
}

int led_2g_off(void)
{
        int fd;

        fd = open("/sys/class/gpio/gpio" LED4_GPIO_CTRL "/value", O_WRONLY);
        if(fd < 0)
                return 1;

        write(fd, "1", 1);
        close(fd);

        return 0;
}

int led_5g_on(void)
{
        int fd;

        fd = open("/sys/class/gpio/gpio" LED5_GPIO_CTRL "/value", O_WRONLY);
        if(fd < 0)
                return 1;

        write(fd, "0", 1);
        close(fd);

        return 0;
}

int led_5g_off(void)
{
        int fd;

        fd = open("/sys/class/gpio/gpio" LED5_GPIO_CTRL "/value", O_WRONLY);
        if(fd < 0)
                return 1;

        write(fd, "1", 1);
        close(fd);

        return 0;
}
#endif

void led_init()
{
        // open red led file
        fd_rx = open(RLED_DEV_PATH, O_WRONLY);
        if(fd_rx < 0)
        {
                printf("Fail to Open %s device\n", RLED_DEV_PATH);
                exit(1);
        }

        // open green led file
        fd_tx = open(GLED_DEV_PATH, O_WRONLY);
        if(fd_tx < 0)
        {
                printf("Fail to Open %s device\n", GLED_DEV_PATH);
                exit(1);
        }

        // open blue led file
        fd_eth = open(BLED_DEV_PATH, O_WRONLY);
        if(fd_eth < 0)
        {
                printf("Fail to Open %s device\n", BLED_DEV_PATH);
                exit(1);
        }

        fd_2g = open(LED_2G_DEV_PATH, O_WRONLY);
        fd_5g = open(LED_5G_DEV_PATH, O_WRONLY);

        write(fd_2g, "0", 1); 
        write(fd_5g, "0", 1); 
}

int key_fd;
void key_init()
{
        /*打开文件*/
        key_fd = open("/dev/input/event1", O_RDONLY);

        if (key_fd < 0)
        {
                printf("open file : /dev/input/event1 error!\n");
        }
}

/**
 * @brief compare time difference
 * 
 * @param tv0 
 * @param tv1 
 * @return double 
 */
double timeval_diff(struct timeval * tv0, struct timeval * tv1)
{
        double time1, time2;

        time1 = tv0->tv_sec + (tv0->tv_usec / 1000000.0);
        time2 = tv1->tv_sec + (tv1->tv_usec / 1000000.0);

        time1 = time1 - time2;
        if (time1 < 0)
                time1 = -time1;

        return time1;
}

/**
 * @brief key thread
 * 
 * @return void* 
 */
void *key_process()
{
        int error = -20;
        struct timeval key_start_ticks, key_release_ticks;
        double time_diff;

        /*读取按键状态*/
        while(1)
        {
                error = read(key_fd, &button_input_event, sizeof(button_input_event));
                if (error < 0)
                {
                        printf("read file error! \n");
                }

                /*判断并打印按键状态*/
                if(button_input_event.type != EV_SYN)
                {
                        if(button_input_event.value == 0)
                        {
                                key_release_ticks.tv_sec    = button_input_event.time.tv_sec;
                                key_release_ticks.tv_usec = button_input_event.time.tv_usec;

                                time_diff = timeval_diff(&key_release_ticks, &key_start_ticks);
                                printf("time_diff = %f\n", time_diff);
                                if(time_diff >= 3)
                                {
                                        //绿灯亮
                                        write(fd_tx, "255", 3);
                                        //延时1s
                                        sleep(1);
                                        //绿灯灭
                                        write(fd_tx, "0", 1);

                                        default_ip_addr();
					system("reboot");
                                }
                        }
                        else
                        {
                                key_start_ticks.tv_sec    = button_input_event.time.tv_sec;
                                key_start_ticks.tv_usec = button_input_event.time.tv_usec;
                        }
                }

                usleep(50000);
        }
}
